﻿using HelperFromTheSkeleton.Common;
using HelperFromTheSkeleton.EFBaseRepository;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;

namespace HelperFromTheSkeleton.Model.DomainModels
{
    public class BaseUnitWorkImpl : IBaseUnitWork, IDisposable
    {
        private readonly DbContext _dbContext;
        private readonly IDbContextTransaction _transaction;
        private readonly ILoggerFactory _loggerFactory;
        //private readonly
        public BaseUnitWorkImpl(DbContext dbContext)
        {
            _dbContext = dbContext;
            _transaction = _dbContext.Database.BeginTransaction();
            _loggerFactory = Config.GetServer<ILoggerFactory>() ?? throw new InvalidOperationException("日志服务为空");
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public void Add<T>(T entity) where T : BaseDomain
        {
            var nowTime = DateTime.Now;
            if (entity.ID == Guid.Empty)
            {
                entity.ID = Guid.NewGuid();
            }
            entity.DateAddTime = nowTime;
            entity.DateUpTime = nowTime;
            _dbContext.Set<T>().Add(entity);
            _dbContext.Entry(entity).State = EntityState.Added;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public void Delete<T>(T entity) where T : BaseDomain
        {
            _dbContext.Entry(entity).State = EntityState.Deleted;
        }

        /// <summary>
        /// 软删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public void SoftDelete<T>(T entity) where T : BaseDomain
        {
            entity.DateUpTime = DateTime.Now;
            entity.IsDelete = true;
            _dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Updata<T>(T entity) where T : BaseDomain
        {
            entity.DateUpTime = DateTime.Now;
            _dbContext.Entry(entity).State = EntityState.Modified;
        }

        /// <summary>
        /// 提交
        /// </summary>
        /// <returns></returns>
        public async Task CommitAsync()
        {
            try
            {
                await _dbContext.SaveChangesAsync();
                await _transaction.CommitAsync();
                DetachedAll();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                var _logger = _loggerFactory?.CreateLogger("DbUpdateErrorLog");
                _logger?.LogError(ex, ex.Message);
                foreach (var val in ex.Entries)
                {
                    val.Reload();
                }
                await _transaction.RollbackAsync();
                DetachedAll();
            }
        }

        /// <summary>
        /// 取消所有跟踪的实例
        /// </summary>
        private void DetachedAll()
        {
            IEnumerable<EntityEntry> entities = _dbContext.ChangeTracker.Entries();
            foreach (var val in entities)
            {
                if (val != null)
                {
                    val.State = EntityState.Detached;
                }
            }
        }

        public void Dispose()
        {
            _transaction.Dispose();
        }
    }
}
